// 函数指针示例
#include <stdio.h>
#include <stdlib.h>

// 几个示例函数

void print()
{
	printf("哈哈哈\n");
}

void print1()
{
	printf("哈哈哈哈哈哈\n");
}

int sum(int a, int b)
{
	return a + b;
}

void printInt(int a)
{
	printf("%d ", a);
}

int *pointer()
{
	int *a = (int *)malloc(sizeof(int));
	*a = 11;
	return a;
}

// 把函数指针作为函数参数传递（回调函数）

// 函数声明（注意类型的表示）
void traverse(int[], void (*)(int));

/// @brief 遍历数组元素（回调函数例子）
/// @param array 数组
/// @param callback 回调函数，无返回值，一个int参数
void traverse(int array[], void (*callback)(int))
{
	// 遍历前面3个用回调函数访问
	int i;
	for (i = 0; i < 3; i++)
	{
		callback(array[i]);
	}
	printf("\n");
}

// 函数返回函数指针
// 返回一个返回值为int，带两个int参数的函数指针
// 函数本身名为fun，本身无参数
int (*fun())(int, int)
{
	return sum;
}

// 函数返回函数指针，带参数型
// 返回一个返回值为void，不带参数的函数指针
// 函数本身名为fun1，带一个int参数
void (*fun1(int a))()
{
	if (a == 1)
	{
		return print1;
	}
	return print;
}

int main()
{
	// 函数指针p：无参，返回类型void
	// 让函数指针p指向print函数
	void (*p)() = print;
	//执行p
	p();
	// 函数指针sp：两个int参数，返回类型int
	// 让函数指针sp指向sum函数
	int (*sp)(int, int);
	// 执行sp
	printf("%d\n", sum(1, 2));
	// 一个返回类型为指针的函数指针
	// 把pointer赋值给函数指针ip
	int *(*ip)() = pointer;
	printf("%d\n", *ip());
	// 一个长度为2的函数指针数组fp[2]，其中函数指针是void无参函数
	void (*fp[2])();
	// 给函数指针数组中元素赋值
	fp[0] = print;
	fp[1] = print1;
	// 执行它们
	fp[0]();
	fp[1]();
	// 使用回调函数
	int arr[] = {1, 2, 3};
	traverse(arr, printInt);
	// 执行返回函数指针的函数得到函数指针，将函数返回值赋值给函数指针getSum
	int (*getSum)(int, int) = fun();
	printf("%d\n", getSum(3, 4));
	// 传参的返回函数指针的函数，下面两个分别赋值给函数指针pp1，pp2
	void (*pp1)() = fun1(1);
	void (*pp2)() = fun1(0);
	// 执行
	pp1();
	pp2();
	// 输出函数指针类型变量的大小，可见使用"返回值 (*)(参数)"可以表示一个函数指针类型的指针变量
	printf("%d %d %d\n", sizeof(void (*)()), sizeof(void (*)(int)), sizeof(int (*)()));
	// 给一个无参无返回值类型的函数指针分配内存
	void (*mfp)() = (void (*)())malloc(sizeof(void (*)()));
	mfp = print1;
	// 执行
	mfp();
	return 0;
}